/**
 * Copyright 2018-2019 jianggujin (www.jianggujin.com).
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.jianggujin.modulelink.util;

import java.beans.Introspector;
import java.lang.reflect.Field;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.ResourceBundle;

import com.jianggujin.modulelink.JModule;
import com.jianggujin.modulelink.support.annotation.JOrder;
import com.jianggujin.modulelink.util.JLogFactory.JLog;

/**
 * 模块工具类
 *
 */
public class JModuleUtils {

    private static final JLog logger = JLogFactory.getLog(JModuleUtils.class);

    /**
     * 销毁模块，不抛出异常
     *
     * @param module 需要销毁的模块
     */
    public static void destroyQuietly(JModule module) {
        if (module != null && !module.isDestroyed()) {
            try {
                if (logger.isInfoEnabled()) {
                    logger.info("Destroy module: " + module.getModuleConfig());
                }
                module.destroy();
                destroyQuietly(module.getModuleClassLoader());
            } catch (Exception e) {
                logger.error("Failed to destroy module " + module.getModuleConfig(), e);
            }
        }
    }

    /**
     * 销毁类加载器，不抛出异常
     * 
     * @param classLoader 类加载器
     */
    public static void destroyQuietly(ClassLoader classLoader) {
        Introspector.flushCaches();
        if (classLoader != null) {
            try {
                // 从已经使用给定类加载器加载的缓存中移除所有资源包
                if (classLoader != null) {
                    ResourceBundle.clearCache(classLoader);
                    if (classLoader instanceof JModuleClassLoader) {
                        ((JModuleClassLoader) classLoader).close();
                    }
                }
            } catch (Exception e) {
                logger.error("Failed to destroy", e);
            }
        }
    }

    /**
     * 排序
     * 
     * @param orders
     */
    public static void sortOrder(List<?> orders) {
        if (orders == null || orders.isEmpty()) {
            return;
        }
        Collections.sort(orders, new Comparator<Object>() {
            @Override
            public int compare(Object order1, Object order2) {
                JOrder o1 = order1.getClass().getAnnotation(JOrder.class);
                JOrder o2 = order2.getClass().getAnnotation(JOrder.class);
                int ov1 = o1 != null ? o1.value() : 0;
                int ov2 = o2 != null ? o2.value() : 0;
                if (ov1 < ov2) {
                    return -1;
                } else if (ov1 == ov2) {
                    return 0;
                }
                return 1;
            }
        });
    }

    /**
     * 注入
     * 
     * @param field
     * @param target
     * @param value
     * @throws Exception
     */
    public static void inject(Field field, Object target, Object value) throws Exception {
        boolean accessible = field.isAccessible();
        try {
            field.setAccessible(true);
            field.set(target, value);
        } finally {
            field.setAccessible(accessible);
        }
    }
}
